package com.ken.ability.gateway.filter.auth;

import com.ken.ability.auth.protocol.security.AuthUserDetails;
import com.ken.common.core.utils.BeanCopyUtils;
import com.ken.common.core.utils.JsonUtils;
import com.ken.entity.auth.AuthUser;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.Optional;

/**
 * 过滤器 获取认证的用户信息
 */
@Component
public class AuthInfoFilter implements GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return ReactiveSecurityContextHolder.getContext()
                .flatMap(securityContext -> Mono.just(Optional.of(securityContext)))
                .defaultIfEmpty(Optional.empty())
                .flatMap(securityContextOptional -> {
                    //如果为null的情况
                    if (!securityContextOptional.isPresent()) {
                        return chain.filter(exchange);
                    }

                    //如果不为null
                    AuthUserDetails authUserDetails = securityContextOptional
                            .map(securityContexts -> securityContexts.getAuthentication())
                            .map(authentication -> authentication.getPrincipal())
                            .filter(o -> o instanceof AuthUserDetails)
                            .map(o -> (AuthUserDetails) o)
                            .get();

                    //将Security对象拷贝到普通的do对象中
                    AuthUser authUser = BeanCopyUtils.copyBean(authUserDetails, AuthUser.class);
                    String authUserJson = JsonUtils.obj2Json(authUser);

                    //获得旧请求
                    ServerHttpRequest oldRequest = exchange.getRequest();
                    URI uri = oldRequest.getURI();

                    //定义新的消息头
                    HttpHeaders headers = oldRequest.getHeaders();
                    HttpHeaders newHttpHeader = new HttpHeaders();
                    newHttpHeader.putAll(headers);
                    try {
                        newHttpHeader.add("auth_user", URLEncoder.encode(authUserJson, "UTF-8"));
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }

                    //构建新请求
                    ServerHttpRequest newRequest = oldRequest.mutate().uri(uri).build();
                    newRequest = new ServerHttpRequestDecorator(newRequest) {
                        @Override
                        public HttpHeaders getHeaders() {
                            return newHttpHeader;
                        }
                    };

                    return chain.filter(exchange.mutate().request(newRequest).build());
                });
    }
}
